package com.nunbey.lingxi.activities;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Chronometer;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;

import com.neurosky.thinkgear.HeartFitnessLevel;
import com.neurosky.thinkgear.NeuroSkyHeartMeters;
import com.neurosky.thinkgear.TGDevice;
import com.nunbey.lingxi.R;
import com.nunbey.lingxi.apis.EcgApi;
import com.nunbey.lingxi.lincat.activityinit.BaseActivity;

import com.nunbey.lingxi.lincat.datastore.SharedPreferencesHelper;
import com.nunbey.lingxi.lincat.dialog.AlertDialogCreator;
import com.nunbey.lingxi.lincat.retrofitutil.RetrofitUtil;
import com.nunbey.lingxi.module.ecg.EcgCanvas;
import com.nunbey.lingxi.module.ecg.EcgPainter;
import com.nunbey.lingxi.module.mode.record.EcgRecordPost;
import com.nunbey.lingxi.module.mode.record.EcgRecordReceive;

import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.json.JSONObject;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Set;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * @author 李一帆
 * @description 该活动是ECG模块的核心代码：
 * @description 视图层控件的获取和初始化
 * @description ECG设备的控制，初始化和数据的处理与刷新
 * @description 蓝牙设备自动查询，连接，授权等
 */
public class EcgActivity extends BaseActivity {

    /* 绘图模块开始：控件从上到下的顺序，对应着实际逻辑从外向内的包含关系**/
    /**
     * 绘图画布的容器
     */
    private LinearLayout drawContainer;
    /**
     * 绘图绘制后的结果图
     */
    private GraphicalView drawView;
    /**
     * 绘图画布
     */
    private EcgCanvas ecgCanvas;
    /**
     * 绘图画笔
     */
    private EcgPainter ecgPainter;
    /**
     * 绘图数据的容器，数据源
     */
    private XYMultipleSeriesDataset dataset;
    ;
    /**
     * 绘图数据的实际内容
     */
    private XYSeries series;


    /**
     * 绘图控件初始化
     */
    private void drawControllerInit(){
        //画布初始化
        this.ecgCanvas = new EcgCanvas();
        //画笔初始化
        this.ecgPainter = new EcgPainter();
        //添加画笔
        this.ecgCanvas.addSeriesRenderer(this.ecgPainter);
        //数据初始化：创建时需要指定数据名称
        this.series = new XYSeries("heart-rate");
        //数据源初始化
        this.dataset = new XYMultipleSeriesDataset();
        //将数据添加进数据源
        this.dataset.addSeries(series);
        //数据生成测试
        //this.generateTestData();
        //生成结果
        drawView = ChartFactory.getLineChartView(EcgActivity.this, dataset, ecgCanvas);
        //找到画布容器->将结果添加入画布容器中
        drawContainer = (LinearLayout)findViewById(R.id.activity_ecg_drawScreen);
        drawContainer.addView(drawView,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT));
    }



    /**
     * 生成测试数据：用于测试
     */
    private void generateTestData(){
        for(int i=0;i<100;i++){
            series.add(i,Math.random()*100);
        }
    }


    /* 绘图模块结束**/




    /*数据可视化模块开始*/
    /**
     * 定时器
     */
    private Chronometer chronometer;

    private TextView heartRateTextView;

    private TextView r_r_intervalTextView;

    private TextView respirationTextView;

    /* 数据可视化模块结束**/




    /*心电监护仪器模块开始*/

    /**
     * @description ecg消息处理器
     */
    private EcgMessageHandler ecgHandler;
    /**
     * @description 监护仪
     */
    private TGDevice tgDevice;
    /**
     * @description 信号量
     */
    private int signal;

    /**
     * 实时心率
     */
    private int tempHeartRate;


    /**
     * @description 用于展示的心率列表
     */

    private int [] showedRateList;
    /**
     * 全部数据
     */
    private ArrayList<Integer> totalData;
    /**
     * @description 放松度
     */
    private int relaxation;
    /**
     * @description 呼吸率
     */
    private float respiration;
    /**
     * @description 心脏年龄
     */
    private int heartAge;
    /**
     * @description R间隔
     */
    private int r_r_interval;



    /**
     * @description TG设备初始化
     */
    private void tgDeviceInit(){
        chronometer = findViewById(R.id.activity_ecg_clock);
        heartRateTextView = findViewById(R.id.activity_ecg_heartRate);
        r_r_intervalTextView = findViewById(R.id.activity_ecg_rtor);
        respirationTextView = findViewById(R.id.activity_respiration);
        // setBase():设置计时器的起始时间
        chronometer.setBase(SystemClock.elapsedRealtime());
        Toast.makeText(this,"设备已连接",Toast.LENGTH_LONG).show();
        tgDevice.setBlinkDetectionEnabled(true);
        tgDevice.setRespirationRateEnable(true);
        tgDevice.pass_seconds = 15;
        showedRateList = new int[100];
        totalData = new ArrayList<>();
        //tgDevice.inputAge = ;
        tgDevice.start();
        deviceStartMark = true;
        chronometer.start();
    }


    /**
     * @description 更新图表
     */
    private void updateCharts(){
        //根据心率数刷新折线颜色
        if((tempHeartRate<60&&tempHeartRate>30)||(tempHeartRate>100&&tempHeartRate<160))
            ecgPainter.setColor(Color.YELLOW);
        else if(tempHeartRate<30||tempHeartRate>160)
            ecgPainter.setColor(Color.RED);
        else
            ecgPainter.setColor(Color.WHITE);
        //向总数据中添加
        if(totalData.size()<=3600)
            totalData.add(tempHeartRate);
        int size = series.getItemCount();
        //向展示数据中添加
        if(size==100){
            for(int i=0;i<99;i++){
                showedRateList[i] = showedRateList[i+1];
            }
            showedRateList[size-1] = tempHeartRate;
        }
        else
            showedRateList[size] = tempHeartRate;
        dataset.removeSeries(series);
        series.clear();
        if(size==100)
            for(int i=0;i<size;i++)
                series.add(i,showedRateList[i]);
        else
            for(int i=0;i<=size;i++)
                series.add(i,showedRateList[i]);

        dataset.addSeries(series);
        drawView.invalidate();
    }

    /**
     * @description TG设备关闭
     */
    private void tgDeviceStop(boolean normal){
        if(chronometer!=null){
            chronometer.stop();
            chronometer.setBase(SystemClock.elapsedRealtime());// setBase():设置计时器的起始时间
            chronometer.setText("00:00");//输入框清空
        }
        if(heartRateTextView !=null)
            heartRateTextView.setText("0");
        if(r_r_intervalTextView !=null)
            r_r_intervalTextView.setText("R_R_interval: 0");
        if(respirationTextView != null)
            respirationTextView.setText("Respiration: 0");
        if(tgDevice != null)
            tgDevice.stop();
        dataset.removeSeries(series);
        series.clear();
        dataset.addSeries(series);
        drawView.invalidate();
        //正常结束
        if(normal)
            generateResult();
        if(!normal&&deviceStartMark) //非正常关闭
            Toast.makeText(this, "设备非正常关闭，结束监护", Toast.LENGTH_SHORT).show();
        deviceStartMark = false;
        bondedMark = false;
        findViewById(R.id.activity_ecg_start_controller).setBackgroundColor(Color.parseColor("#006400"));

    }
    private AlertDialog queryDialog;
    /**
     * 生成结果
     */
    private void generateResult(){
        if(totalData ==null){
            return;
        }
        if(totalData.size()>=10){
             queryDialog = AlertDialogCreator.getQueryDialog(this, "记录询问", "您是否要记录此次监护的结果？", "是", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    //模拟获取用户个人信息
                    String gender = "Male";
                    int age = 22;
                    //计算结果
                    Integer[] dataBuffer = new Integer[totalData.size()];
                    //平均心率
                    int averageRate = 0;
                    for (int k = 0;k < totalData.size(); k++) {
                        averageRate += totalData.get(k);
                        dataBuffer[k] = totalData.get(k);
                    }
                    averageRate /= totalData.size();
                    //心脏风险度：HRV:0,1,2,3 风险度上升
                    int heartRiskAwareness = NeuroSkyHeartMeters.calculateHeartRiskAware(dataBuffer);
                    //心脏强弱
                    HeartFitnessLevel heartFitnessLevel = new HeartFitnessLevel();
                    String heartFitnessLevelLabel = heartFitnessLevel.getHeartFitnessLevel(age, gender, averageRate);
                    //构造数据并发送请求
                    //取token
                    SharedPreferencesHelper sharedPreferencesHelper = new SharedPreferencesHelper();
                    String token = sharedPreferencesHelper.getData(EcgActivity.this,"userInfo","token");
                    //Log.e("token",token);
                    //构造post数据并发请求编写回调函数
                    EcgRecordPost ecgRecord = new EcgRecordPost(totalData,averageRate,heartRiskAwareness,heartAge,relaxation,respiration,heartFitnessLevelLabel,r_r_interval);
                    EcgApi ecgApi = (EcgApi) RetrofitUtil.getApiInstance(EcgApi.class);
                    ecgApi.recordAndDistinguish(ecgRecord,token).enqueue(new Callback<ResponseBody>(){
                        @Override
                        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                            try {
                                String resultJson = response.body().string();
                                JSONObject result = new JSONObject(resultJson);
                                int code = result.getInt("code");
                                Log.e("code",Integer.toString(code));
                                if(code ==0){
                                    JSONObject data = result.getJSONObject("data");
                                    EcgRecordReceive recordReceive = new EcgRecordReceive(data.getLong("recordId"),data.getInt("averageRate"),data.getInt("heartRiskAwareness"),data.getInt("heartAge"),data.getInt("relaxation"),data.getInt("respiration"),data.getString("heartFitnessLevelLabel"),data.getInt("r_r_interval"),data.getString("distinguish"),LocalDateTime.now());
                                    EcgRecordActivity.startEcgRecordActivity(EcgActivity.this,recordReceive);
                                }else
                                    Toast.makeText(EcgActivity.this, "系统错误！", Toast.LENGTH_SHORT).show();

                            }catch (Exception e){
                                e.printStackTrace();
                                Log.e(EcgActivity.class.toString(),"系统错误");
                            }
                        }
                        @Override
                        public void onFailure(Call<ResponseBody> call, Throwable throwable) {

                        }
                    });

                }
            }, "否",null);
            queryDialog.show();

        }else
            Toast.makeText(this, "设备关闭。有效数据不足，记录无意义", Toast.LENGTH_SHORT).show();


    }

    /**
     * 跳转到ECG列表
     * @param view
     */
    public void navigateToEcgRecordList(View view) {
        EcgRecordListActivity.startEcgRecordListActivity(this);
    }


    /**
     * @description ECG设备向手机传输数据的处理器
     */
    @SuppressLint("HandlerLeak")
    private final class EcgMessageHandler extends Handler{
        private int notFoundTryCount = 0;
        @SuppressLint("SetTextI18n")
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                //设备状态发送改变
                case TGDevice.MSG_STATE_CHANGE:{
                    switch (msg.arg1) {
                        //设备已连接
                        case TGDevice.STATE_CONNECTED:
                            EcgActivity.this.tgDeviceInit();
                            break;
                        //设备未找到
                        case TGDevice.STATE_NOT_FOUND:
                            Toast.makeText(EcgActivity.this, "ECG设备未能成功连接，正在第"+notFoundTryCount+"次尝试连接设备",Toast.LENGTH_LONG).show();
                            notFoundTryCount++;
                            if(notFoundTryCount<=5)
                                tgDevice.connect(bluetoothDevice);
                            else {
                                Toast.makeText(EcgActivity.this, "ECG设备未开启或连接失败",Toast.LENGTH_LONG).show();
                                EcgActivity.this.tgDeviceStop(false);
                            }
                            break;
                        //设备结束连接
                        case TGDevice.STATE_DISCONNECTED:
                            EcgActivity.this.tgDeviceStop(false);
                            break;
                        //蓝牙断开
                        case TGDevice.STATE_ERR_BT_OFF:
                            Toast.makeText(EcgActivity.this, "蓝牙已断开",Toast.LENGTH_LONG).show();
                            EcgActivity.this.tgDeviceStop(false);
                            break;
                    }
                    break;
                }
                //电量低
                case TGDevice.MSG_LOW_BATTERY:{
                    Toast.makeText(getApplicationContext(), "设备电量不足", Toast.LENGTH_LONG).show();
                    break;
                }
                //信号量
                case TGDevice.MSG_POOR_SIGNAL:{
                    signal = msg.arg1;
                    break;
                }
                //实时真实心率
                case TGDevice.MSG_HEART_RATE:{
                    if(signal==200){
                        tempHeartRate = msg.arg1;
                        heartRateTextView.setText(Integer.toString(tempHeartRate));
                        //计算心率加速度，平滑的心率
                        updateCharts();
                    }else
                        Toast.makeText(getApplicationContext(), "设备穿戴0", Toast.LENGTH_LONG).show();
                    break;
                }
                //放松度
                case TGDevice.MSG_RELAXATION:{
                    relaxation = msg.arg1;
                    //Log.e("relaxation",Integer.toString(relaxation));
                    break;
                }
                //呼吸率
                case TGDevice.MSG_RESPIRATION:{
                    respiration = (Float)msg.obj;
                    respirationTextView.setText("Respiration: "+Float.toString(respiration));
                    //Log.e("respiration",Float.toString(respiration));
                    break;
                }
                //R间隔
                case TGDevice.MSG_EKG_RRINT:{
                    r_r_interval = msg.arg1;
                    //Log.e("r_r_interval",Integer.toString(r_r_interval));
                    r_r_intervalTextView.setText("R_R_interval: "+Integer.toString(r_r_interval));
                    break;
                }
                //心脏年龄
                case TGDevice.MSG_HEART_AGE:{
                    heartAge = msg.arg1;
                    Log.d("heartAge",Integer.toString(heartAge));
                    break;
                }
                default:
                    break;
            }
        }
    }

    /*心电监护仪模块结束*/



    /*蓝牙和监护仪设备模块开始*/
    /**
     * 设备启动状态
     */
    private boolean deviceStartMark;
    /**
     * 绑定标志
     */
    private boolean bondedMark;
    /**
     * @description 蓝牙适配器
     */
    private BluetoothAdapter bluetoothAdapter;
    /**
     * @description 本机设备
     */
    private BluetoothDevice bluetoothDevice;
    /**
     * @description 设备名称
     */
    private final String deviceName = "Xinweilai";

    /**
     * @description 请求启动蓝牙
     */
    private final int REQUEST_OPEN_BT_CODE = 0;
    /**
     * @description 请求开启手机定位
     */
    private final int REQUEST_OPEN_LOCATION = 1;

    /**
     * @description 搜索蓝牙设备的广播监听器
     */
    BroadcastReceiver btBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            //搜索到新的蓝牙设备，根据设备名称（不唯一）判断它是否是活动所需要的设备，如果是则尝试进行绑定
            if(action.equals(BluetoothDevice.ACTION_FOUND)){
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if(device!=null&&device.getName()!=null&&device.getName().equals(deviceName)) {
                    device.createBond();
                }
            }
            if(action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)){
                Toast.makeText(context,"蓝牙搜索结束，未搜索到设备\n或者您仅同意本次开启定位权限，需要使用时开启权限才能自动搜索", Toast.LENGTH_SHORT).show();
            }
            //蓝牙设备状态改变接收到消息
            if(action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)){
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if(device.getName().equals(deviceName)){
                    EcgActivity.this.bluetoothDevice = device;
                    if(device.getBondState()==BluetoothDevice.BOND_BONDED){
                        ((EcgActivity)context).bondedTip();
                    }
                    if(device.getBondState() == BluetoothDevice.BOND_NONE)
                        Toast.makeText(context, device.getName()+"设备取消绑定", Toast.LENGTH_SHORT).show();
                }
            }
        }
    };


    /**
     * 注册广播监听
     */
    private void registerBTBroadcast(){
        IntentFilter intentFilter = new IntentFilter();
        //设备发现
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        //设备状态改变
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        //蓝牙结束搜索
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        //进行注册监听
        this.registerReceiver(btBroadcastReceiver,intentFilter);
    }

    /**
     * @description 用户按下按钮，请求绑定设备
     * @param view
     */
    public void connectControl(View view) {
        try {
            if(!bondedMark){
                bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                if(bluetoothAdapter==null){
                    Toast.makeText(this, "本机蓝牙不可用", Toast.LENGTH_SHORT).show();
                    return;
                }
                //未打开蓝牙，才需要打开蓝牙
                if (!bluetoothAdapter.isEnabled()) {
                    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                    this.startActivityForResult(intent, REQUEST_OPEN_BT_CODE);
                }
                //蓝牙已开启
                else
                    this.checkDeviceAfterBTInit();
            }
            else
                Toast.makeText(this, "设备已绑定", Toast.LENGTH_SHORT).show();
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    /**
     * 用户询问开启权限的回调
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //蓝牙权限
        if(requestCode == REQUEST_OPEN_BT_CODE){
            if(resultCode==120){
                this.checkDeviceAfterBTInit();
            }
            if(resultCode==0)
                Toast.makeText(this, "请启动蓝牙以便让ECG设备发现", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 蓝牙开启后检查设备是否加入蓝牙连接列表
     */
    private void checkDeviceAfterBTInit(){
        Toast.makeText(this, "蓝牙已开启", Toast.LENGTH_SHORT).show();
        boolean searchMark = true;
        /**
         * @description 搜索到的蓝牙设备
         */
        Set<BluetoothDevice> bluetoothDevices = bluetoothAdapter.getBondedDevices();
        for(BluetoothDevice bluetoothDevice: bluetoothDevices){
            //设备已经在绑定列表
            if(bluetoothDevice.getName().equals(deviceName)){
                Toast.makeText(this, "设备已和手机绑定", Toast.LENGTH_SHORT).show();
                this.bluetoothDevice = bluetoothDevice;
                this.bondedTip();
                searchMark = false;
                break;
            }
        }
        //设备不在绑定列表：开始搜索设备
        if(searchMark){
            if(bluetoothAdapter.isDiscovering())
                Toast.makeText(this, "正在搜索设备，请稍等...", Toast.LENGTH_SHORT).show();
            else {
                Toast.makeText(this, "无连接记录，开始搜索设备...", Toast.LENGTH_SHORT).show();
                //搜索设备前需要申请开启获取手机定位权限
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    //未开启定位权限:进行申请
                    if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
                        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_OPEN_LOCATION);
                    //已开启权限，开始搜索
                    else
                        bluetoothAdapter.startDiscovery();
                }
            }

        }
    }

    /**
     * 开启手机位置信息动态权限申请回调
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        //同意开启手机定位权限，开始回调
        if(requestCode==REQUEST_OPEN_LOCATION){
            if(grantResults[0]==0)
                bluetoothAdapter.startDiscovery();
            else
                AlertDialogCreator.getConfirmDialog(this,"申请权限提示",
                        "请您同意开启定位才能自动连接设备。您也可以选择手动连接蓝牙","确定",null).show();
        }
    }

    /**
     * 设备蓝牙绑定后的操作
     */
    private void bondedTip(){
        bondedMark = true;
        ecgHandler = new EcgMessageHandler();
        tgDevice = new TGDevice(bluetoothAdapter, ecgHandler);
    }




    /*蓝牙和监护仪设备模块结束*/


    @Override
    public void onCreate(Bundle savedInstancedState) {
        super.onCreate(savedInstancedState);
        //去掉标题栏
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        this.setContentView(R.layout.activity_ecg);
        //绘图模块初始化
        this.drawControllerInit();
        //注册蓝牙广播监听
        this.registerBTBroadcast();
        //设备启动状态和设备连接状态初始化
        deviceStartMark = false;
        bondedMark = false;
    }

    @Override
    protected void onStart() {
        super.onStart();
        deviceStartMark = false;
        bondedMark = false;
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        this.tgDeviceStop(false);
        findViewById(R.id.activity_ecg_start_controller).setBackgroundColor(Color.GREEN);
        deviceStartMark = false;
        bondedMark = false;
        if(queryDialog != null)
            queryDialog.dismiss();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        this.tgDeviceStop(false);
        if(queryDialog != null)
            queryDialog.dismiss();
    }

    public static void startEcgActivity(Context context){
        context.startActivity(new Intent(context,EcgActivity.class));
    }

    /**
     * 启动或关闭设备
     * @param view
     */
    public void startOrStopDevice(View view) {
        //设备未启动
        if(!deviceStartMark){
            //设备未绑定
            if(!bondedMark)
                Toast.makeText(this, "请先绑定设备", Toast.LENGTH_SHORT).show();
            //设备已经绑定，ecg设备连接蓝牙
            else{
                tgDevice.connect(this.bluetoothDevice);
                findViewById(R.id.activity_ecg_start_controller).setBackgroundColor(Color.parseColor("#8B0000"));
            }

        }
        //设备已经启动
        else
            this.tgDeviceStop(true);
    }

}
